﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Forms;
using System.Windows.Input;
using MediaPlayer.Model;
using MediaPlayer.ViewModel.Tools;

namespace MediaPlayer.ViewModel
{
    class PlayerViewModel : ViewModelBase
    {
        #region Fields
        private readonly ObservableCollection<PlayListViewModel> playLists;
        private readonly ICollectionView collectionViewPlayList;

        private ICommand playButton;
        private ICommand browseButton;
        private ICommand prevButton;
        private ICommand nextButton;

        private ICommand fullScreen;
        private ICommand newPlayListCommand;
        private ICommand addCommand;
        private ICommand removeCommand;

        private bool isPlaying = false;
        private bool isFullScreen = false;

        private string currentlyPlaying;

        private Uri filename;
        private PlayList playList = new PlayList();

        private MainWindow mainWindow;
        private int indexPlayList = 0;
        private string searchText;

        public string SearchText
        {
            set
            {
                if (value == "")
                    this.SelectedPlayList.ResetView();
                else
                    this.SelectedPlayList.DoQuery(value);
            }
            get
            {
                return this.searchText;
            }
        }

        #endregion

        #region Properties
        public ICommand NextButton
        {
            get
            {
                if (this.nextButton == null)
                    this.nextButton = new MyCommand(() => this.playNext(), () => this.CanPlayNext());

                return this.nextButton;
            }

        }

        public ICommand RemoveCommand
        {
            get
            {
                if (this.removeCommand == null)
                    this.removeCommand = new MyCommand(() => this.RemoveSong(), () => this.CanRemoveSong());

                return this.removeCommand;
            }
        }

        public ICommand AddCommand
        {
            get
            {
                if (this.addCommand == null)
                    this.addCommand = new MyCommand(() => this.AddSong(), () => this.CanAddSong());
                return this.addCommand;
            }
        }

        public ICommand NewPlayListCommand
        {
            get
            {
                if (newPlayListCommand == null)
                {
                    newPlayListCommand = new MyCommand(() =>
                        {
                            this.playLists.Add(new PlayListViewModel(new PlayList()
                            {
                                Name = "PlayList",
                            }));
                        });
                }
                return newPlayListCommand;
            }
        }

        public ICommand FullScreen
        {
            get
            {
                if (this.fullScreen == null)
                    this.fullScreen = new MyCommand(() => this.SetFullScreen());
                return this.fullScreen;
            }
        }

        public ICommand PrevButton
        {
            get
            {
                if (this.prevButton == null)
                    this.prevButton = new MyCommand(() => this.PreviousMedia(), () => CanPlayPrev());
                return this.prevButton;
            }
        }

        public ICommand PlayButton
        {
            get
            {
                if (this.playButton == null)
                    this.playButton = new MyCommand(() => this.PlayPlayer(), () => CanPlay());
                return this.playButton;
            }
        }

        public ICommand BrowseButton
        {
            get
            {
                if (this.browseButton == null)
                    this.browseButton = new MyCommand(() => this.BrowseFile());
                return this.browseButton;
            }
        }
        #endregion

        #region Misc
        public Uri FileName
        {
            get
            {
                return this.filename;
            }
            set
            {
                if (value != filename)
                    this.filename = value;
                this.OnPropertyChanged("FileName");
            }
        }

        public string CurrentlyPlaying
        {
            get
            {
                return this.currentlyPlaying;
            }
            set
            {
                if (value != this.currentlyPlaying)
                    this.currentlyPlaying = value;
                this.OnPropertyChanged("CurrentlyPlaying");
            }
        }

        public PlayListViewModel SelectedPlayList
        {
            get
            {
                return this.collectionViewPlayList.CurrentItem as PlayListViewModel;
            }
        }

        public ObservableCollection<PlayListViewModel> PlayLists
        {
            get
            {
                return this.playLists;
            }
        }

        public ICollectionView CollectionViewPlayList
        {
            get
            {
                return this.collectionViewPlayList;
            }
        }

        #endregion

        #region Constructor

        public PlayerViewModel()
        {
        }

        public PlayerViewModel(MainWindow mainWindow)
        {
            this.mainWindow = mainWindow;
            this.playLists = new ObservableCollection<PlayListViewModel>();

            foreach (PlayList playList in PlayList.GetPlayListFromXml())
            {
                this.playLists.Add(new PlayListViewModel(playList));
            }
            this.collectionViewPlayList = new ListCollectionView(this.playLists);

            if (this.collectionViewPlayList == null)
                throw new NullReferenceException("collectionViewPlayList");
            this.collectionViewPlayList.CurrentChanged += new EventHandler(this.OnCollectionViewPlayListCurrentChanged);
        }

        ~PlayerViewModel()
        {
            PlayList.SetPlayListToXml(this.ConvertOCToList());
        }

        #endregion

        #region Private Methode

        private void isCurrentlyPlaying()
        {
            if (this.playList.SongList[indexPlayList].Album != null)
            {
                Song song;

                song = this.playList.SongList[indexPlayList];
                this.CurrentlyPlaying = song.AlbumArtist[0] + "\t - \t" + song.Name;
                this.FileName = new Uri(song.FullPath);
            }
            else
            {
                this.CurrentlyPlaying = this.playList.SongList[indexPlayList].FileName;
                this.FileName = new Uri(this.playList.SongList[indexPlayList].FullPath);
            }
        }

        private void SetFullScreen()
        {
            //marche pas
            if (!isFullScreen)
            {
                this.mainWindow.LayoutRoot.Children.Remove(this.mainWindow.PlayerView.PlayerLayout);
                //this.mainWindow.Content = this.mainWindow.PlayerView.MediaLayout;
                this.mainWindow.WindowState = WindowState.Maximized;
                this.mainWindow.WindowStyle = WindowStyle.None;
            }
            else
            {
                this.mainWindow.Content = this.mainWindow.LayoutRoot;
                this.mainWindow.LayoutRoot.Children.Add(this.mainWindow.PlayerView.PlayerLayout);
                this.mainWindow.WindowState = WindowState.Normal;
                this.mainWindow.WindowStyle = WindowStyle.SingleBorderWindow;
            }
            isFullScreen = !isFullScreen;
        }

        private bool CanPlayPrev()
        {
            if (this.indexPlayList > 0 || this.isPlaying == true)
                return true;
            return false;
        }

        private bool CanPlayNext()
        {
            if (this.indexPlayList + 1 < this.playList.SongList.Count)
                return true;
            return false;
        }

        private void playNext()
        {
            indexPlayList++;
            this.isCurrentlyPlaying();
        }

        private List<PlayList> ConvertOCToList()
        {
            var data = new List<PlayList>();

            foreach (PlayListViewModel playListVM in this.playLists)
            {
                data.Add(playListVM.PlayList);
            }
            return data;
        }

        private void PlayPlayer()
        {
            if (isPlaying == true)
            {
                this.mainWindow.PlayerView.media.Pause();
                isPlaying = false;
            }
            else
            {
                if (this.playList != null && this.playList.SongList.Count != 0)
                {
                    this.FileName = new Uri(this.playList.SongList[indexPlayList].FullPath);
                    this.mainWindow.PlayerView.media.Play();
                    this.isCurrentlyPlaying();
                    isPlaying = true;
                }
            }
        }

        private void PreviousMedia()
        {

            if (this.mainWindow.PlayerView.media.Position.Seconds > 1)
            {
                TimeSpan ts = new TimeSpan(0);
                this.mainWindow.PlayerView.media.Position = ts;
            }
            else if (this.indexPlayList > 0)
            {
                indexPlayList--;
                this.FileName = new Uri(this.playList.SongList[indexPlayList].FullPath);
            }

        }

        private void BrowseFile()
        {
            OpenFileDialog dlg = MyFileBrowser.FileDialog;
            DialogResult result = dlg.ShowDialog();

            if (result == DialogResult.OK)
            {
                playList.SongList.Clear();
                foreach (string file in dlg.FileNames)
                {
                    playList.AddSong(this.GetSongWithTag(file));
                }
                this.FileName = new System.Uri(playList.SongList[0].FullPath);
                this.indexPlayList = 0;
                this.PlayPlayer();
            }
        }

        private bool CanAddSong()
        {
            return this.playLists.Count > 0;
        }

        private void AddSong()
        {
            if (this.SelectedPlayList != null)
            {
                OpenFileDialog dlg = MyFileBrowser.FileDialog;
                DialogResult result = dlg.ShowDialog();

                if (result == DialogResult.OK)
                {
                    FileAttributes attributes = File.GetAttributes(dlg.FileName);

                    if (attributes == FileAttributes.Directory)
                    {
                        Task task = new Task(() => this.AddSongFromDirectory(new DirectoryInfo(dlg.FileName)));

                        task.Start();
                    }
                    else
                    {
                        foreach (string file in dlg.FileNames)
                        {
                            this.PutSongInList(file);
                        }

                    }
                }
            }
        }

        private void AddSongFromDirectory(DirectoryInfo directory)
        {
            foreach (FileInfo file in directory.GetFiles())
            {
                this.PutSongInList(file.FullName);
                //if (directory)
                //    this.AddSongFromDirectory(directory)
            }
        }

        private void PutSongInList(string songFileName)
        {
            Song song = GetSongWithTag(songFileName);

            this.SelectedPlayList.Songs.Add(song);
            this.SelectedPlayList.PlayList.AddSong(song);
        }

        private Song GetSongWithTag(string songFileName)
        {
            TagLib.File tagFile = TagLib.File.Create(songFileName);
            Song song = new Song()
            {
                Name = tagFile.Tag.Title,
                AlbumArtist = tagFile.Tag.Performers,
                Album = tagFile.Tag.Album,
                FullPath = songFileName,
            };

            return song;
        }

        private bool CanPlay()
        {
            if (this.playList.SongList.Count != 0)
                return true;
            return false;
        }

        private bool CanRemoveSong()
        {
            return this.playLists.Count > 0;
        }

        private void RemoveSong()
        {
            if (this.SelectedPlayList != null)
            {
                if (this.SelectedPlayList.Songs.Count == 0)
                    this.PlayLists.Remove(this.SelectedPlayList);
                else
                {
                    Song songToRemove = this.SelectedPlayList.SelectedSong;

                    this.SelectedPlayList.Songs.Remove(songToRemove);
                    this.SelectedPlayList.PlayList.RemoveSong(songToRemove);
                }
            }
        }
        #endregion

        #region Event
        private void OnCollectionViewPlayListCurrentChanged(object sender, EventArgs e)
        {
            this.OnPropertyChanged("SelectedPlayList");
            this.SelectedPlayList.ResetView();
            if (this.SelectedPlayList != null)
            {
                this.playList = this.SelectedPlayList.PlayList;
                this.indexPlayList = 0;
            }
        }

        public void MediaEnded(object sender, RoutedEventArgs e)
        {
            if (this.indexPlayList < this.playList.SongList.Count)
            {
                indexPlayList++;
                this.FileName = new Uri(this.playList.SongList[indexPlayList].FullPath);
            }
        }
        #endregion
    }
}
